package internal

import (
	"fmt"
	"os"
	"path/filepath"
	"sync"
	"time"

	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

// default_logger 默认的日志
var default_logger Logger
var logger_lock sync.Mutex

// LogWriter 日志记录工具
func newWriteSyncer(name string) zapcore.WriteSyncer {
	file := filepath.Join("./logs", fmt.Sprintf("%s.%s.log", "%y-%m-%d", name))
	rl, err := rotatelogs.New(file)
	if err != nil {
		panic(err)
	}
	return zapcore.AddSync(rl)
}

func CreateLogger(level zapcore.LevelEnabler) Logger {
	ec := zap.NewDevelopmentEncoderConfig()
	ec.EncodeTime = func(t time.Time, pae zapcore.PrimitiveArrayEncoder) {
		pae.AppendString("\x1b[38;5;238m> ")
		pae.AppendString(t.Format("15:04:05.000"))
	}

	ec.EncodeLevel = func(l zapcore.Level, pae zapcore.PrimitiveArrayEncoder) {
		pae.AppendString(l.String())
	}

	ec.EncodeCaller = func(caller zapcore.EntryCaller, pae zapcore.PrimitiveArrayEncoder) {
		pae.AppendString(caller.TrimmedPath())
		pae.AppendString("\x1b[0m\n")
	}
	ec.ConsoleSeparator = " "
	console := zapcore.NewConsoleEncoder(ec)

	fec := zap.NewProductionEncoderConfig()
	json := zapcore.NewJSONEncoder(fec)

	std := zapcore.NewCore(console, zapcore.AddSync(os.Stdout), level)

	debug := zapcore.NewCore(json, newWriteSyncer("debug"), zap.DebugLevel)
	info := zapcore.NewCore(json, newWriteSyncer("info"), zap.InfoLevel)
	warn := zapcore.NewCore(json, newWriteSyncer("warn"), zap.WarnLevel)
	err := zapcore.NewCore(json, newWriteSyncer("error"), zap.ErrorLevel)

	tee := zapcore.NewTee(std, debug, info, warn, err)
	return zap.New(tee, zap.AddCaller())
}

// Logger 日志
type Logger interface {
	Debug(msg string, fields ...zap.Field)
	Info(msg string, fields ...zap.Field)
	Warn(msg string, fields ...zap.Field)
	Error(msg string, fields ...zap.Field)
	Panic(msg string, fields ...zap.Field)
}

func DefaultLogger() Logger {
	logger_lock.Lock()
	defer func() {
		logger_lock.Unlock()
	}()
	if default_logger != nil {
		return default_logger
	}
	default_logger = CreateLogger(zap.DebugLevel)
	return default_logger
}
